package site.sorghum.ddl.base;

import site.sorghum.ddl.annotation.*;
import site.sorghum.ddl.defaults.JavaTypeToJdbcTypeConverter;
import site.sorghum.ddl.entity.DdlColumnWrap;
import site.sorghum.ddl.entity.DdlTableWrap;
import site.sorghum.ddl.extra.ClassUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.JDBCType;
import java.util.ArrayList;
import java.util.List;

public class JavaCoreEntityGenerate {

    /**
     * Java的类 -> 数据库表元数据
     *
     * @param tClass 类名
     * @return 数据库表元数据
     */
    public DdlTableWrap get(Class<?> tClass) {
        DdlTableWrap coreDdlTableWrap = getCoreDdlTableWrap(tClass);
        List<Field> fields = ClassUtil.fetchAllFields(tClass);
        for (Field field : fields) {
            DdlColumnWrap coreDdlColumnWrap = getCoreDdlColumnWrap(coreDdlTableWrap.getName(), field, coreDdlTableWrap.getPks());
            if (coreDdlColumnWrap == null) {
                continue;
            }
            coreDdlTableWrap.getColumns().add(coreDdlColumnWrap);
        }
        resort(coreDdlTableWrap.getColumns());
        return coreDdlTableWrap;
    }

    /**
     * 获取数据库表元数据
     */
    public DdlTableWrap getCoreDdlTableWrap(Class<?> tClass) {
        String tableName = camelCaseToUnderline(tClass.getSimpleName());
        String tableRemarks = "";
        DdlAlias ddlAlias = getAnnotation(tClass, DdlAlias.class);
        if (ddlAlias != null && !ddlAlias.value().isEmpty()) {
            tableName = ddlAlias.value();
            tableRemarks = ddlAlias.remarks();
        }
        List<DdlColumnWrap> columns = new ArrayList<>();
        List<String> pks = new ArrayList<>();
        return DdlTableWrap.builder().name(tableName).remarks(tableRemarks).pks(pks).columns(columns).indexes(null).build();
    }

    /**
     * 获取数据库列元数据
     */
    public DdlColumnWrap getCoreDdlColumnWrap(String tableName, Field field, List<String> pks) {
        // static字段 忽略处理
        if (Modifier.isStatic(field.getModifiers())) {
            return null;
        }
        // transient 字段忽略
        if (Modifier.isTransient(field.getModifiers())) {
            return null;
        }
        DdlExclude annotation = getAnnotation(field, DdlExclude.class);
        if (annotation != null) {
            return null;
        }
        String columnName = camelCaseToUnderline(field.getName());
        DdlAlias fieldAlias = getAnnotation(field, DdlAlias.class);
        if (fieldAlias != null && !fieldAlias.value().isEmpty()) {
            columnName = fieldAlias.value();
        }
        JDBCType jdbcType = JavaTypeToJdbcTypeConverter.getJdbcType(field.getType());
        DdlType ddlType = getAnnotation(field, DdlType.class);
        DdlColumnWrap.DdlColumnWrapBuilder columnWrapBuilder = DdlColumnWrap
                .builder();
        if (ddlType != null) {
            if (!ddlType.value().isEmpty()) {
                columnWrapBuilder.dbType(ddlType.value());
            }
            columnWrapBuilder.size(ddlType.size());
            if (ddlType.digit() > 0) {
                columnWrapBuilder.digit(ddlType.digit());
            }
            columnWrapBuilder.isNullable(ddlType.nullable());
        } else {
            columnWrapBuilder.isNullable(true);
        }
        DdlWeight ddlWeight = getAnnotation(field, DdlWeight.class);
        if (ddlWeight != null) {
            columnWrapBuilder.weight(ddlWeight.weight());
        }
        DdlIndex ddlIndex = getAnnotation(field, DdlIndex.class);
        if (ddlIndex != null){
            columnWrapBuilder.indexGroup(ddlIndex.group()).unique(ddlIndex.unique());
        }
        DdlColumnWrap column = columnWrapBuilder
                .table(tableName)
                .name(columnName)
                .ddlType(jdbcType)
                .build();
        Annotation ddlId = getAnnotation(field, DdlId.class);
        if (ddlId != null) {
            pks.add(columnName);
        }
        return column;
    }


    /**
     * 重新排序
     * @param ddlColumnWraps 重新排序
     */
    public void resort(List<DdlColumnWrap> ddlColumnWraps){
        // coreDdlTableWrap.getColumns() 按照weight排序 相同weight值得原排序优先 不同weight值的 weight越大越考前
        ddlColumnWraps.sort((o1, o2) -> {
            if (o1.getWeight() == o2.getWeight()) {
                return 0;
            }
            return o1.getWeight() > o2.getWeight() ? -1 : 1;
        });
    }
    /**
     * 驼峰转下划线
     */
    private String camelCaseToUnderline(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        StringBuilder result = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char currentChar = input.charAt(i);
            if (Character.isUpperCase(currentChar)) {
                if (i > 0) {
                    result.append('_');
                }
                result.append(Character.toLowerCase(currentChar));
            } else {
                result.append(currentChar);
            }
        }
        return result.toString();
    }


    /**
     * 获取注解
     */
    public <T extends Annotation> T getAnnotation(Class<?> tClass, Class<T> annotationClass) {
        return tClass.getAnnotation(annotationClass);
    }

    /**
     * 获取注解
     */
    public <T extends Annotation> T getAnnotation(Field field, Class<T> annotationClass) {
        return field.getAnnotation(annotationClass);
    }
}
